package com.yanqu.road.server.manager.union.huaben;

import com.yanqu.road.entity.union.cross.CrossUnionInfo;
import com.yanqu.road.entity.union.cross.CrossUnionMember;
import com.yanqu.road.entity.union.huaben.UnionHuaBenBaseTempData;
import com.yanqu.road.entity.union.huaben.UnionHuaBenServerGroup;
import com.yanqu.road.entity.union.huaben.config.UnionHuaBenConfigInfo;
import com.yanqu.road.logic.bussiness.union.cross.CrossHuaBenBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.pb.union.cross.UnionHuaBenProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.union.CrossUnionMgr;
import com.yanqu.road.server.manger.UnionHuaBenServerGroupMgr;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.ConfigHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class CrossUnionHuaBenConfigMgr extends TempMgr {

    /**
     * 难度/关卡
     */
    static Map<Integer, Map<Integer, UnionHuaBenConfigInfo>> configMap;

    /**
     * 周id/区服id/难度/关卡
     */
    static Map<Integer, Map<Long, Map<Integer, Map<Integer, UnionHuaBenBaseTempData>>>> weekServerTempMap;

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        configMap = CrossHuaBenBussiness.getUnionHuaBenConfigInfoMap();
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        int thisWeedId = getThisWeekId();
        int preWeedId = getPreWeekId();
        weekServerTempMap = CrossHuaBenBussiness.getUnionHuaBenBaseTempDataMap(thisWeedId, preWeedId);
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    @Override
    public boolean save() {

        for (Map.Entry<Integer, Map<Long, Map<Integer, Map<Integer, UnionHuaBenBaseTempData>>>> entry : weekServerTempMap.entrySet()) {
            for (Map.Entry<Long, Map<Integer, Map<Integer, UnionHuaBenBaseTempData>>> mapEntry : entry.getValue().entrySet()) {
                for (Map.Entry<Integer, Map<Integer, UnionHuaBenBaseTempData>> levelMapEntry : mapEntry.getValue().entrySet()) {
                    for (Map.Entry<Integer, UnionHuaBenBaseTempData> dataEntry : levelMapEntry.getValue().entrySet()) {
                        if(dataEntry.getValue().isInsertOption()){
                            CrossHuaBenBussiness.addUnionHuaBenBaseTempData(dataEntry.getValue());
                        }else if(dataEntry.getValue().isUpdateOption()){
                            CrossHuaBenBussiness.updateUnionHuaBenBaseTempData(dataEntry.getValue());
                        }
                    }
                }
            }
        }
        return true;
    }

    static Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> getWeekServerTempData(int weekId, long serverId){
        Map<Long, Map<Integer, Map<Integer, UnionHuaBenBaseTempData>>> serverMap = weekServerTempMap.get(weekId);
        if(serverMap == null){
            return null;
        }
        return serverMap.get(serverId);
    }

    static Map<Integer, UnionHuaBenBaseTempData> getWeekServerTempData(int weekId, long serverId, int degree){
        Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> degreeMap = getWeekServerTempData(weekId, serverId);
        if(degreeMap == null){
            return null;
        }
        return degreeMap.get(degree);
    }

    static UnionHuaBenBaseTempData getWeekServerTempData(int weekId, long serverId, int degree, int level){
        Map<Long, Map<Integer, Map<Integer, UnionHuaBenBaseTempData>>> serverMap = weekServerTempMap.get(weekId);
        if(serverMap == null){
            return null;
        }
        Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> degreeMap =  serverMap.get(serverId);
        if(degreeMap == null){
            return null;
        }
        Map<Integer, UnionHuaBenBaseTempData> levelMap = degreeMap.get(degree);
        if(levelMap == null){
            return null;
        }
        return levelMap.get(level);
    }

    public static void generateWeekTemp(){

        int channelId = ConfigHelper.getInt("channelId");
        int thisWeekId = getThisWeekId();
        Map<Integer, UnionHuaBenServerGroup> groupMap = UnionHuaBenServerGroupMgr.getServerGroupMap(channelId);
        if(groupMap == null){
            return;
        }

        Map<Long, Map<Integer, Map<Integer, UnionHuaBenBaseTempData>>> serverTempMap = weekServerTempMap.get(thisWeekId);
        if(serverTempMap == null){
            synchronized (weekServerTempMap){
                serverTempMap = weekServerTempMap.get(thisWeekId);
                if(serverTempMap == null){
                    weekServerTempMap.put(thisWeekId, new ConcurrentHashMap<>());
                }
            }
            serverTempMap = weekServerTempMap.get(thisWeekId);
        }

        synchronized (serverTempMap) {

            for (UnionHuaBenServerGroup group : groupMap.values()) {
                //区服内是否已有配置
                int groupDataExistNum = 0;
                long existServerId = 0l;
                for (long serverId : group.getServerList()) {
                    if (serverTempMap.containsKey(serverId)) {
                        groupDataExistNum ++;
                        existServerId = serverId;
                    }
                }

                if(groupDataExistNum == group.getServerList().size()){
                    //生成缺失的区服配置
                    Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> otherServerMap = serverTempMap.get(existServerId);
                    //检测缺失的配置
                    //可能中途加话本，本周又要开
                    for (Map.Entry<Integer, Map<Integer, UnionHuaBenConfigInfo>> configEntry : configMap.entrySet()) {
                        int degree = configEntry.getKey();
                        if(!otherServerMap.containsKey(degree)){
                            //补生成这个难度的关卡

                            //生成整个分组配置
                            Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> baseMap = generateBaseTemp();
                            if(baseMap.size() == 0){
                                continue;
                            }
                            //取缺失的难度
                            Map<Integer, UnionHuaBenBaseTempData> degreeBaseMap = baseMap.get(degree);
                            if(degreeBaseMap == null || degreeBaseMap.size() == 0){
                                continue;
                            }
                            generateServerTemp(thisWeekId, degree, otherServerMap, degreeBaseMap, existServerId);
                            getLogger().info("weekId {} 区服 {}， 补生成话本模板   难度 {} ", thisWeekId, existServerId, degree);

                            for (long serverId : group.getServerList()) {
                                if(serverId == existServerId){
                                    continue;
                                }
                                Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> tempServerMap = serverTempMap.get(serverId);
                                if(tempServerMap != null && !tempServerMap.containsKey(degree)){
                                    generateServerTemp(thisWeekId, degree, tempServerMap, degreeBaseMap, serverId);
                                    getLogger().info("weekId {} 区服 {}， 补生成话本模板   难度 {} ", thisWeekId, serverId, degree);
                                }
                            }
                        }
                    }
                    continue;
                }

                if(existServerId == 0){
                    //生成整个分组配置
                    Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> baseMap = generateBaseTemp();
                    if(baseMap.size() == 0){
                        continue;
                    }
                    for (long serverId : group.getServerList()) {
                        generateServerTemp(thisWeekId, serverTempMap, baseMap, serverId);
                    }
                }else {
                    //生成缺失的区服配置
                    Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> otherServerMap = serverTempMap.get(existServerId);
                    for (long serverId : group.getServerList()) {
                        if(!serverTempMap.containsKey(serverId)){
                            generateServerTemp(thisWeekId, serverTempMap, otherServerMap, serverId);
                        }
                    }
                }
            }
        }
    }

    /**
     * @param thisWeekId 周
     * @param serverTempMap 父容器
     * @param baseMap 模板参照
     * @param serverId 区服
     */
    private static void generateServerTemp(int thisWeekId, Map<Long, Map<Integer, Map<Integer, UnionHuaBenBaseTempData>>> serverTempMap,
                                           Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> baseMap, long serverId) {
        Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> serverBaseMap = new ConcurrentHashMap<>();
        for (Map.Entry<Integer, Map<Integer, UnionHuaBenBaseTempData>> entry : baseMap.entrySet()) {
            for (Map.Entry<Integer, UnionHuaBenBaseTempData> dataEntry : entry.getValue().entrySet()) {
                UnionHuaBenBaseTempData cloneData = cloneTempData(dataEntry.getValue());
                cloneData.setWeekId(thisWeekId);
                cloneData.setServerId(serverId);
                cloneData.setInsertOption();
                if (serverBaseMap.get(cloneData.getDegree()) == null) {
                    serverBaseMap.put(cloneData.getDegree(), new ConcurrentHashMap<>());
                }
                serverBaseMap.get(cloneData.getDegree()).put(cloneData.getLevel(), cloneData);
            }
        }
        serverTempMap.put(serverId, serverBaseMap);
    }

    private static void generateServerTemp(int thisWeekId, int degree, Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> serverTempMap,
                                           Map<Integer, UnionHuaBenBaseTempData> baseMap, long serverId) {
        Map<Integer, UnionHuaBenBaseTempData> copyMap = new ConcurrentHashMap<>();
        if(!serverTempMap.containsKey(degree)){
            for (Map.Entry<Integer, UnionHuaBenBaseTempData> dataEntry : baseMap.entrySet()) {
                UnionHuaBenBaseTempData cloneData = cloneTempData(dataEntry.getValue());
                cloneData.setWeekId(thisWeekId);
                cloneData.setServerId(serverId);
                cloneData.setInsertOption();
                copyMap.put(cloneData.getLevel(), cloneData);
            }
            serverTempMap.put(degree, copyMap);
        }
    }

    public static Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> generateBaseTemp(){
        if(configMap == null || configMap.size() == 0){
            return new ConcurrentHashMap<>();
        }
        Random random = new Random();
        //随机boss
        List<List<Integer>> bossList = getBossKey();
        //小怪
        List<List<Integer>> monsterLis = getMonsterAppearance();

        List<List<Integer>> bossListResult = new ArrayList<>();
        List<List<Integer>> monsterLisResult = new ArrayList<>();
        while (bossList.size() > 0){
            int idx = random.nextInt(bossList.size());
            bossListResult.add(bossList.remove(idx));
            monsterLisResult.add(monsterLis.remove(idx));
        }


        Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> baseTempMap = new ConcurrentHashMap<>();
        for (Map.Entry<Integer, Map<Integer, UnionHuaBenConfigInfo>> entry : configMap.entrySet()) {
            for (Map.Entry<Integer, UnionHuaBenConfigInfo> infoEntry : entry.getValue().entrySet()) {
                UnionHuaBenConfigInfo config = infoEntry.getValue();
                UnionHuaBenBaseTempData temp = new UnionHuaBenBaseTempData();

                temp.setId(config.getId());
                temp.setDegree(config.getDegree());
                temp.setLevel(config.getLevel());
                temp.setBossHP(config.getBossHP());
                List<Integer> waveList = StringUtils.stringToIntegerList(config.getMonsterWave(), ";");
                int wave = waveList.get(0) + random.nextInt(waveList.get(1) - waveList.get(0) + 1);
                BigInteger totalBlood = new BigInteger(config.getMonsterHP());
                temp.setMonsterHP(totalBlood.divide(BigInteger.valueOf(wave * 5)).toString());
                temp.setMonsterWave(wave);
                temp.setMonsterReward(config.getMonsterReward());
                temp.setBossReward(config.getBossReward());

                List<Integer> boss = bossListResult.get(temp.getLevel() - 1);

                temp.setBossIcon(boss.get(0));
                temp.setBossSReward(boss.get(1) + "=" + config.getBossSRNum());

                temp.setMonsterIcon(new ArrayList<>(monsterLisResult.get(temp.getLevel() - 1)));

                temp.setProbability(config.getProbability());

                if(baseTempMap.get(temp.getDegree()) == null){
                    baseTempMap.put(temp.getDegree(), new ConcurrentHashMap<>());
                }
                temp.setBossScore(config.getBossScore());
                temp.setMonsterScore(config.getMonsterScore());
                baseTempMap.get(temp.getDegree()).put(temp.getLevel(), temp);
            }
        }

        return baseTempMap;
    }

    /**
     * boss形象/奖励 配置
     */
    public static List<List<Integer>> getBossKey(){
        List<List<Integer>> tempList = new ArrayList<>();
        List<String> list = StringUtils.stringToStringList(GameConfig.UNION_STORY_BOSS_KEY, "\\|");
        for (String s : list) {
            tempList.add(StringUtils.stringToIntegerList(s, ";"));
        }
        return tempList;
    }

    /**
     * 小怪形象配置
     */
    public static List<List<Integer>> getMonsterAppearance(){
        List<List<Integer>> tempList = new ArrayList<>();
        List<String> list = StringUtils.stringToStringList(GameConfig.UNION_STORY_MONSTER_APPEARANCE, "\\|");
        for (String s : list) {
            tempList.add(StringUtils.stringToIntegerList(s, ";"));
        }
        return tempList;
    }

    /**
     * 克隆
     */
    public static UnionHuaBenBaseTempData cloneTempData(UnionHuaBenBaseTempData src){
        UnionHuaBenBaseTempData clone = new UnionHuaBenBaseTempData();
        clone.setWeekId(src.getWeekId());
        clone.setServerId(src.getServerId());
        clone.setId(src.getId());
        clone.setDegree(src.getDegree());
        clone.setLevel(src.getLevel());
        clone.setBossHP(src.getBossHP());
        clone.setMonsterHP(src.getMonsterHP());
        clone.setMonsterWave(src.getMonsterWave());
        clone.setMonsterReward(src.getMonsterReward());
        clone.setBossReward(src.getBossReward());
        clone.setBossSReward(src.getBossSReward());
        clone.setProbability(src.getProbability());
        clone.setBossIcon(src.getBossIcon());
        clone.setMonsterIcon(new ArrayList<>(src.getMonsterIcon()));
        clone.setBossScore(src.getBossScore());
        clone.setMonsterScore(src.getMonsterScore());
        return clone;
    }

    public static int getStroyMissionExistTime(int degree){
        List<Integer> timeList = StringUtils.stringToIntegerList(GameConfig.UNION_STORY_MISSION_EXIST_TIME, "\\|");
        if(timeList.size() >= degree){
            return timeList.get(degree - 1);
        }
        return 0;
    }

    //前一周id
    public static int getPreWeekId() {
        Calendar now = Calendar.getInstance();
        Date monday = DateHelper.getThisWeekMonday(now.getTime());
        now.setTime(monday);
        now.add(Calendar.HOUR, -7 * 24);
        return Integer.valueOf(DateHelper.getPyyyyMMddDateString(now.getTimeInMillis() / 1000));
    }

    //本周id
    public static int getThisWeekId(){
        Calendar now = Calendar.getInstance();
        Date monday = DateHelper.getThisWeekMonday(now.getTime());
        now.setTime(monday);
        return Integer.valueOf(DateHelper.getPyyyyMMddDateString(now.getTimeInMillis() / 1000));
    }


    /**
     * 下发话本配置
     */
    public static void syncConfig(CrossUnionInfo crossUnionInfo, CrossUnionMember member){
        if(!crossUnionInfo.isCross()){
            return;
        }

        int weekId = getThisWeekId();

        Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> tempDataMap = getWeekServerTempData(weekId, crossUnionInfo.getServerId());
        if(tempDataMap == null){
            return;
        }

        UnionHuaBenProto.UnionHuaBenConfigSync.Builder syncMsg = buildHuaBenConfig(tempDataMap);

        MessageHelper.sendPacket(member.getServerId(), member.getUserId(), YanQuMessageUtils.buildMessage(Protocol.U_CROSS_UNION_HUA_BEN_CONFIG_SYNC, syncMsg));

    }

    private static UnionHuaBenProto.UnionHuaBenConfigSync.Builder buildHuaBenConfig(Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> tempDataMap) {
        UnionHuaBenProto.UnionHuaBenConfigSync.Builder syncMsg = UnionHuaBenProto.UnionHuaBenConfigSync.newBuilder();
        for (Map.Entry<Integer, Map<Integer, UnionHuaBenBaseTempData>> entry : tempDataMap.entrySet()) {
            for (Map.Entry<Integer, UnionHuaBenBaseTempData> dataEntry : entry.getValue().entrySet()) {
                UnionHuaBenBaseTempData tempData = dataEntry.getValue();
                UnionHuaBenProto.UnionHuaBenConfigTemp.Builder configBuilder = UnionHuaBenProto.UnionHuaBenConfigTemp.newBuilder();
                configBuilder.setDegree(tempData.getDegree());
                configBuilder.setLevel(tempData.getLevel());
                configBuilder.setBossHP(tempData.getBossHP());
                configBuilder.setMonsterHP(tempData.getMonsterHP());
                configBuilder.setMonsterWave(tempData.getMonsterWave());
                configBuilder.setMonsterReward(tempData.getMonsterReward());
                configBuilder.setBossSReward(tempData.getBossSReward());
                configBuilder.setBossReward(tempData.getBossReward());
                configBuilder.setProbability(tempData.getProbability());
                configBuilder.setBossIcon(tempData.getBossIcon());
                configBuilder.addAllMonsterIcon(tempData.getMonsterIcon());
                syncMsg.addConfig(configBuilder);
            }
        }
        return syncMsg;
    }

    /**
     * 下发话本配置
     */
    public static void syncConfig(CrossUnionInfo crossUnionInfo){
        if(!crossUnionInfo.isCross()){
            return;
        }

        int weekId = getThisWeekId();

        Map<Integer, Map<Integer, UnionHuaBenBaseTempData>> tempDataMap = getWeekServerTempData(weekId, crossUnionInfo.getServerId());
        if(tempDataMap == null){
            return;
        }

        UnionHuaBenProto.UnionHuaBenConfigSync.Builder syncMsg = buildHuaBenConfig(tempDataMap);

        Map<Long, CrossUnionMember> memberMap = CrossUnionMgr.getUnionMemberMap(crossUnionInfo.getUnionUid());
        if(memberMap != null){
            for (Map.Entry<Long, CrossUnionMember> entry : memberMap.entrySet()) {
                MessageHelper.sendPacket(entry.getValue().getServerId(), entry.getValue().getUserId(), YanQuMessageUtils.buildMessage(Protocol.U_CROSS_UNION_HUA_BEN_CONFIG_SYNC, syncMsg));
            }
        }
    }
}
